package org.xian.token.secutiry;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Service;
import org.springframework.web.filter.OncePerRequestFilter;
import org.xian.token.entity.SysUser;
import org.xian.token.exception.CustomException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Jwt 拦截器，通过Token鉴权
 *
 */
@SuppressWarnings("SpringJavaAutowiringInspection")
@Service
public class TokenFilter extends OncePerRequestFilter {


    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {
        // 存储Token的Headers Key与Value
        final String authorizationKey = "Authorization";
        String authorizationValue;
        try {
            authorizationValue = request.getHeader(authorizationKey);
            // Token 开头部分
            String bearer = "Bearer ";
            if (authorizationValue != null && authorizationValue.startsWith(bearer)) {
                // token
                String token = authorizationValue.substring(bearer.length());
                // 验证用户的token信息，一旦认证的token没有问题则认为用户合法！认证通过则将用户的用户名和角色信息交与授权的
                SysUser sysUser = TokenUtils.validationToken(token);
                if (sysUser != null) {
                    // Spring Security 角色名称默认使用 "ROLE_" 开头
                    // authorities.add 可以增加多个用户角色，对于一个用户有多种角色的系统来说，
                    // 可以通过增加用户角色表、用户--角色映射表，存储多个用户角色信息

                    // 传入用户名、用户密码、用户角色。 这里的密码随便写的，用不上
                    UserDetails userDetails = new User(sysUser.getUsername(), "password", sysUser.getAuthorities());
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());

                    authentication.setDetails(userDetails.getUsername());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    // 拿着合法的认证过的信息去授权
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        } catch (Exception e) {
            //this is very important, since it guarantees the user is not authenticated at all

            SecurityContextHolder.clearContext();
            if (e instanceof CustomException) {
                CustomException customException = (CustomException) e;
                response.sendError(customException.getHttpStatus().value(), e.getMessage());
            } else {
                response.sendError(500, e.getMessage());
            }
        }
        filterChain.doFilter(request, response);
    }


}
